package com.acquisition.task.service.impl;

import com.alibaba.fastjson.JSON;
import com.dcs.cn.common.constants.Constants;
import com.dcs.cn.common.constants.Hj212Constants;
import com.dcs.cn.common.service.Hj212Service;
import com.dcs.cn.common.util.ByteUtils;
import com.dcs.cn.common.util.CodeHj212Utils;
import com.dcs.cn.common.util.hj212util.hbt212.core.T212Mapper;
import com.dcs.cn.common.util.hj212util.hbt212.exception.T212FormatException;
import com.dcs.cn.common.util.hj212util.hbt212.model.CpData;
import com.dcs.cn.common.util.hj212util.hbt212.model.Data;
import com.dcs.cn.common.util.hj212util.hbt212.model.Pollution;
import com.dcs.cn.data.domain.DayData;
import com.dcs.cn.data.domain.HourData;
import com.dcs.cn.data.domain.MinuteData;
import com.dcs.cn.data.domain.RealTimeData;
import com.dcs.cn.data.service.DayDataService;
import com.dcs.cn.data.service.HourDataService;
import com.dcs.cn.data.service.MinuteDataService;
import com.dcs.cn.data.service.RealTimeDataService;
import com.dcs.cn.data.service.impl.DayDataServiceImpl;
import com.dcs.cn.data.service.impl.HourDataServiceImpl;
import com.dcs.cn.data.service.impl.MinuteDataServiceImpl;
import com.dcs.cn.data.service.impl.RealTimeDataServiceImpl;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * hj212—2017协议
 * 业务逻辑层实现
 *
 * @author wuqiwei
 * @date 2021/02/22
 */
public class Hj212ServiceImpl implements Hj212Service {

    @Override
    public Map<String, String> hj2017To2017Map(String hj2017) throws IOException, T212FormatException {
        Map<String, String> map = new HashMap<>(16);
        T212Mapper mapper = new T212Mapper().enableDefaultParserFeatures();
        Data data = mapper.readData(hj2017);
        List<String> monitorFactorKey = new ArrayList<>();
        Map<String, Pollution> pollutionMap = data.getCp().getPollution();
        pollutionMap.forEach((k, v) -> monitorFactorKey.add(k));
        map.put(Hj212Constants.HJ212_DATATIME, data.getCp().getDataTime());
        map.put("monitorFactorKey", JSON.toJSONString(monitorFactorKey));
        map.put("data", JSON.toJSONString(data));
        return map;
    }

    @Override
    public Map<String, String> hj2005To2017Map(String hj2005) throws IOException, T212FormatException {
        Map<String, String> map = new HashMap<>(16);
        T212Mapper mapper = new T212Mapper().enableDefaultParserFeatures();
        Data data = mapper.readData(hj2005);
        List<String> monitorFactorKey = new ArrayList<>();
        Map<String, Pollution> pollutionMap = data.getCp().getPollution();
        Map<String, Pollution> newPollutionMap = new HashMap<>(16);
        pollutionMap.forEach((k, v) -> {
            monitorFactorKey.add(CodeHj212Utils.getCode2017By2005(k));
            newPollutionMap.put(CodeHj212Utils.getCode2017By2005(k), v);
        });
        data.getCp().setPollution(newPollutionMap);
        map.put(Hj212Constants.HJ212_DATATIME, data.getCp().getDataTime());
        map.put("monitorFactorKey", JSON.toJSONString(monitorFactorKey));
        map.put("data", JSON.toJSONString(data));
        return map;
    }

    @Override
    public Map<String, String> hebeiTo2017Map(String hebei) {
        Map<String, String> map = new HashMap<>(16);
        CpData cpData = new CpData();
        List<String> monitorFactorKey = new ArrayList<>();
        Map<String, Pollution> pollutionMap = new HashMap<>(16);
        // 参数个数
        int count = Integer.parseInt(hebei.substring(12, 14));
        // 数据段
        String dataSegment = hebei.substring(26, hebei.length() - 8) + "3B";
        for (int i = 0; i < count; i++) {
            String pollutantData = dataSegment.substring(i * 22, (i + 1) * 22);
            // 单个数据段
            pollutantData = pollutantData.substring(0, pollutantData.length() - 2);
            // 污染物key值
            String pollutantKey = CodeHj212Utils.getCode2017ByHebei(pollutantData.substring(0, 6));
            // 污染物类型（2D52：实时数据，2D5A：折算数据）
            String pollutantType = pollutantData.substring(6, 10);
            // 污染物数据标记（P：电源故障、F：排放源停运、C：校验、M：维护、T：超测上限、D：故障、S：设定值、N：正常数据、X：现场检查，现场校验、0：校准数据、1：气象参数、2：异常数据、3：正常数据）
            String pollutantFlag = new String(ByteUtils.hexStrToByteArr(pollutantData.substring(10, 12)));
            // 污染物数值
            BigDecimal pollutantRecord = new BigDecimal(String.valueOf(ByteUtils.hexToFloat(pollutantData.substring(12))));
            // 污染因子，先查看pollutionMap中是否已存在污染物key值，若存在则直接get，否则new
            Pollution pollution;
            if (pollutionMap.containsKey(pollutantKey)) {
                pollution = pollutionMap.get(pollutantKey);
                if (pollution == null) {
                    pollution = new Pollution();
                }
            } else {
                pollution = new Pollution();
            }
            // 监测污染物实时数据标记
            pollution.setFlag(pollutantFlag);
            if ("2D52".equals(pollutantType)) {
                // 污染物实时采样数据
                pollution.setRtd(pollutantRecord);
            } else {
                // 污染物实时采样折算数据
                pollution.setZsRtd(pollutantRecord);
            }
            pollutionMap.put(pollutantKey, pollution);
            monitorFactorKey.add(pollutantKey);
        }
        cpData.setDataTime("20" + hebei.substring(14, 26));
        cpData.setPollution(pollutionMap);
        map.put(Hj212Constants.HJ212_DATATIME, cpData.getDataTime());
        map.put("monitorFactorKey", JSON.toJSONString(monitorFactorKey.stream().distinct().collect(Collectors.toList())));
        map.put("data", JSON.toJSONString(cpData));
        return map;
    }

    @Override
    public String formRealTimeDataToHj212(RealTimeData realTimeData) {
        // 组装的报文
        StringBuilder msg = new StringBuilder();
        // 数据段
        StringBuilder data = new StringBuilder();
        // 指令参数 CP
        StringBuilder cpData = new StringBuilder();
        cpData.append(Hj212Constants.HJ212_CP).append("=&&").append(Hj212Constants.HJ212_DATATIME).append("=").append(realTimeData.getDataTime()).append(";");
        realTimeData.getRealTimeMonitorFactorMap().forEach((key, realTimeMonitorFactor) -> {
            if (realTimeMonitorFactor.getMonitorFactor() != null && !"".equals(realTimeMonitorFactor.getMonitorFactor())) {
                if (realTimeMonitorFactor.getSampleTime() != null) {
                    cpData.append(realTimeMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_SAMPLETIME).append("=").append(realTimeMonitorFactor.getSampleTime()).append(",");
                }
                cpData.append(realTimeMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_RTD).append("=").append(realTimeMonitorFactor.getRtd()).append(",");
                if (realTimeMonitorFactor.getZsRtd() != null && !"".equals(realTimeMonitorFactor.getZsRtd())) {
                    cpData.append(realTimeMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_ZSRTD).append("=").append(realTimeMonitorFactor.getZsRtd()).append(",");
                }
                cpData.append(realTimeMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_FLAG).append("=").append(realTimeMonitorFactor.getFlag()).append(";");
            }
        });
        cpData.append("&&");
        if (realTimeData.getQn() == null || "".equals(realTimeData.getQn())) {
            String qn = new SimpleDateFormat("yyyyMMddHHmmssSSS", Locale.getDefault()).format(Calendar.getInstance().getTime());
            RealTimeDataService realTimeDataService = new RealTimeDataServiceImpl();
            realTimeDataService.updateQn(qn, realTimeData.getId());
            data.append(Hj212Constants.HJ212_QN).append("=").append(qn).append(";");
        } else {
            data.append(Hj212Constants.HJ212_QN).append("=").append(realTimeData.getQn()).append(";");
        }
        data.append(Hj212Constants.HJ212_ST).append("=").append(realTimeData.getSt()).append(";")
                .append(Hj212Constants.HJ212_CN).append("=").append(realTimeData.getCn()).append(";")
                .append(Hj212Constants.HJ212_PW).append("=").append(realTimeData.getPw()).append(";")
                .append(Hj212Constants.HJ212_MN).append("=").append(realTimeData.getMn()).append(";").append("Flag=5;").append(cpData);
        // 数据段长度，例如：长 255，则写为"0255"
        String dataLen = String.format(Locale.getDefault(), "%04d", data.length());
        // 上传信息
        msg.append(Hj212Constants.PACKAGE_HEAD).append(dataLen).append(data).append(crc16(data.toString())).append(Constants.DELIMITER_SYMBOL);
        return msg.toString();
    }

    @Override
    public String formMinuteDataToHj212(MinuteData minuteData) {
        // 组装的报文
        StringBuilder msg = new StringBuilder();
        // 数据段
        StringBuilder data = new StringBuilder();
        // 指令参数 CP
        StringBuilder cpData = new StringBuilder();
        cpData.append(Hj212Constants.HJ212_CP).append("=&&").append(Hj212Constants.HJ212_DATATIME).append("=").append(minuteData.getDataTime()).append(";");
        minuteData.getOtherMonitorFactorMap().forEach((key, otherMonitorFactor) -> {
            if (otherMonitorFactor.getMonitorFactor() != null && !"".equals(otherMonitorFactor.getMonitorFactor())) {
                cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_AVG).append("=").append(otherMonitorFactor.getAvg()).append(",");
                cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_MIN).append("=").append(otherMonitorFactor.getMin()).append(",");
                cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_MAX).append("=").append(otherMonitorFactor.getMax()).append(",");
                if (otherMonitorFactor.getZsAvg() != null && !"".equals(otherMonitorFactor.getZsAvg())) {
                    cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_ZSAVG).append("=").append(otherMonitorFactor.getZsAvg()).append(",");
                }
                if (otherMonitorFactor.getZsMin() != null && !"".equals(otherMonitorFactor.getZsMin())) {
                    cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_ZSMIN).append("=").append(otherMonitorFactor.getZsMin()).append(",");
                }
                if (otherMonitorFactor.getZsMax() != null && !"".equals(otherMonitorFactor.getZsMax())) {
                    cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_ZSMAX).append("=").append(otherMonitorFactor.getZsMax()).append(",");
                }
                if (otherMonitorFactor.getCou() != null && !"".equals(otherMonitorFactor.getCou())) {
                    cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_COU).append("=").append(otherMonitorFactor.getCou()).append(",");
                }
                cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_FLAG).append("=").append(otherMonitorFactor.getFlag()).append(";");
            }
        });
        cpData.append("&&");
        if (minuteData.getQn() == null || "".equals(minuteData.getQn())) {
            String qn = new SimpleDateFormat("yyyyMMddHHmmssSSS", Locale.getDefault()).format(Calendar.getInstance().getTime());
            MinuteDataService minuteDataService = new MinuteDataServiceImpl();
            minuteDataService.updateQn(qn, minuteData.getId());
            data.append(Hj212Constants.HJ212_QN).append("=").append(qn).append(";");
        } else {
            data.append(Hj212Constants.HJ212_QN).append("=").append(minuteData.getQn()).append(";");
        }
        data.append(Hj212Constants.HJ212_ST).append("=").append(minuteData.getSt()).append(";")
                .append(Hj212Constants.HJ212_CN).append("=").append(minuteData.getCn()).append(";")
                .append(Hj212Constants.HJ212_PW).append("=").append(minuteData.getPw()).append(";")
                .append(Hj212Constants.HJ212_MN).append("=").append(minuteData.getMn()).append(";").append("Flag=5;").append(cpData);
        // 数据段长度，例如：长 255，则写为"0255"
        String dataLen = String.format(Locale.getDefault(), "%04d", data.length());
        // 上传信息
        msg.append(Hj212Constants.PACKAGE_HEAD).append(dataLen).append(data).append(crc16(data.toString())).append(Constants.DELIMITER_SYMBOL);
        return msg.toString();
    }

    @Override
    public String formHourDataToHj212(HourData hourData) {
        // 组装的报文
        StringBuilder msg = new StringBuilder();
        // 数据段
        StringBuilder data = new StringBuilder();
        // 指令参数 CP
        StringBuilder cpData = new StringBuilder();
        cpData.append(Hj212Constants.HJ212_CP).append("=&&").append(Hj212Constants.HJ212_DATATIME).append("=").append(hourData.getDataTime()).append(";");
        hourData.getOtherMonitorFactorMap().forEach((key, otherMonitorFactor) -> {
            if (otherMonitorFactor.getMonitorFactor() != null && !"".equals(otherMonitorFactor.getMonitorFactor())) {
                cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_AVG).append("=").append(otherMonitorFactor.getAvg()).append(",");
                cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_MIN).append("=").append(otherMonitorFactor.getMin()).append(",");
                cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_MAX).append("=").append(otherMonitorFactor.getMax()).append(",");
                if (otherMonitorFactor.getZsAvg() != null && !"".equals(otherMonitorFactor.getZsAvg())) {
                    cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_ZSAVG).append("=").append(otherMonitorFactor.getZsAvg()).append(",");
                }
                if (otherMonitorFactor.getZsMin() != null && !"".equals(otherMonitorFactor.getZsMin())) {
                    cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_ZSMIN).append("=").append(otherMonitorFactor.getZsMin()).append(",");
                }
                if (otherMonitorFactor.getZsMax() != null && !"".equals(otherMonitorFactor.getZsMax())) {
                    cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_ZSMAX).append("=").append(otherMonitorFactor.getZsMax()).append(",");
                }
                if (otherMonitorFactor.getCou() != null && !"".equals(otherMonitorFactor.getCou())) {
                    cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_COU).append("=").append(otherMonitorFactor.getCou()).append(",");
                }
                cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_FLAG).append("=").append(otherMonitorFactor.getFlag()).append(";");
            }
        });
        cpData.append("&&");
        if (hourData.getQn() == null || "".equals(hourData.getQn())) {
            String qn = new SimpleDateFormat("yyyyMMddHHmmssSSS", Locale.getDefault()).format(Calendar.getInstance().getTime());
            HourDataService hourDataService = new HourDataServiceImpl();
            hourDataService.updateQn(qn, hourData.getId());
            data.append(Hj212Constants.HJ212_QN).append("=").append(qn).append(";");
        } else {
            data.append(Hj212Constants.HJ212_QN).append("=").append(hourData.getQn()).append(";");
        }
        data.append(Hj212Constants.HJ212_ST).append("=").append(hourData.getSt()).append(";")
                .append(Hj212Constants.HJ212_CN).append("=").append(hourData.getCn()).append(";")
                .append(Hj212Constants.HJ212_PW).append("=").append(hourData.getPw()).append(";")
                .append(Hj212Constants.HJ212_MN).append("=").append(hourData.getMn()).append(";").append("Flag=5;").append(cpData);
        // 数据段长度，例如：长 255，则写为"0255"
        String dataLen = String.format(Locale.getDefault(), "%04d", data.length());
        // 上传信息
        msg.append(Hj212Constants.PACKAGE_HEAD).append(dataLen).append(data).append(crc16(data.toString())).append(Constants.DELIMITER_SYMBOL);
        return msg.toString();
    }

    @Override
    public String formDayDataToHj212(DayData dayData) {
        // 组装的报文
        StringBuilder msg = new StringBuilder();
        // 数据段
        StringBuilder data = new StringBuilder();
        // 指令参数 CP
        StringBuilder cpData = new StringBuilder();
        cpData.append(Hj212Constants.HJ212_CP).append("=&&").append(Hj212Constants.HJ212_DATATIME).append("=").append(dayData.getDataTime()).append(";");
        dayData.getOtherMonitorFactorMap().forEach((key, otherMonitorFactor) -> {
            if (otherMonitorFactor.getMonitorFactor() != null && !"".equals(otherMonitorFactor.getMonitorFactor())) {
                cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_AVG).append("=").append(otherMonitorFactor.getAvg()).append(",");
                cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_MIN).append("=").append(otherMonitorFactor.getMin()).append(",");
                cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_MAX).append("=").append(otherMonitorFactor.getMax()).append(",");
                if (otherMonitorFactor.getZsAvg() != null && !"".equals(otherMonitorFactor.getZsAvg())) {
                    cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_ZSAVG).append("=").append(otherMonitorFactor.getZsAvg()).append(",");
                }
                if (otherMonitorFactor.getZsMin() != null && !"".equals(otherMonitorFactor.getZsMin())) {
                    cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_ZSMIN).append("=").append(otherMonitorFactor.getZsMin()).append(",");
                }
                if (otherMonitorFactor.getZsMax() != null && !"".equals(otherMonitorFactor.getZsMax())) {
                    cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_ZSMAX).append("=").append(otherMonitorFactor.getZsMax()).append(",");
                }
                if (otherMonitorFactor.getCou() != null && !"".equals(otherMonitorFactor.getCou())) {
                    cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_COU).append("=").append(otherMonitorFactor.getCou()).append(",");
                }
                cpData.append(otherMonitorFactor.getMonitorFactor()).append(Hj212Constants.HJ212_FLAG).append("=").append(otherMonitorFactor.getFlag()).append(";");
            }
        });
        cpData.append("&&");
        if (dayData.getQn() == null || "".equals(dayData.getQn())) {
            String qn = new SimpleDateFormat("yyyyMMddHHmmssSSS", Locale.getDefault()).format(Calendar.getInstance().getTime());
            DayDataService dayDataService = new DayDataServiceImpl();
            dayDataService.updateQn(qn, dayData.getId());
            data.append(Hj212Constants.HJ212_QN).append("=").append(qn).append(";");
        } else {
            data.append(Hj212Constants.HJ212_QN).append("=").append(dayData.getQn()).append(";");
        }
        data.append(Hj212Constants.HJ212_ST).append("=").append(dayData.getSt()).append(";")
                .append(Hj212Constants.HJ212_CN).append("=").append(dayData.getCn()).append(";")
                .append(Hj212Constants.HJ212_PW).append("=").append(dayData.getPw()).append(";")
                .append(Hj212Constants.HJ212_MN).append("=").append(dayData.getMn()).append(";").append("Flag=5;").append(cpData);
        // 数据段长度，例如：长 255，则写为"0255"
        String dataLen = String.format(Locale.getDefault(), "%04d", data.length());
        // 上传信息
        msg.append(Hj212Constants.PACKAGE_HEAD).append(dataLen).append(data).append(crc16(data.toString())).append(Constants.DELIMITER_SYMBOL);
        return msg.toString();
    }

    @Override
    public String crc16(String data) {
        char[] charArray = data.toCharArray();
        int i, j, crc, check;
        crc = 0xFFFF;
        for (i = 0; i < data.length(); i++) {
            crc = (crc>>8) ^ charArray[i];
            for (j = 0; j < 8; j++) {
                check = crc & 0x0001;
                crc >>= 1;
                if (check == 0x0001) {
                    crc ^= 0xA001;
                }
            }
        }
        return String.format("%04X", crc);
    }

}
